package jehc.djshi.oauth.client.service.impl;

import jehc.djshi.common.base.BaseHttpSessionEntity;
import jehc.djshi.common.base.BaseResult;
import jehc.djshi.common.base.BaseUtils;
import jehc.djshi.common.base.InitBean;
import jehc.djshi.common.constant.CacheConstant;
import jehc.djshi.common.constant.PathConstant;
import jehc.djshi.common.constant.SessionConstant;
import jehc.djshi.common.constant.StatusConstant;
import jehc.djshi.common.entity.InputEntity;
import jehc.djshi.common.entity.OauthAccountEntity;
import jehc.djshi.common.entity.OauthAdminSysEntity;
import jehc.djshi.common.session.HttpSessionUtils;
import jehc.djshi.common.util.JsonUtil;
import jehc.djshi.common.util.StringUtil;
import jehc.djshi.oauth.client.service.AuthService;
import jehc.djshi.oauth.model.OauthKeyInfo;
import jehc.djshi.oauth.util.OauthUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
 * @Desc 客户端鉴权
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    @Resource
    private OauthUtil oauthUtil;

    @Resource
    BaseUtils baseUtils;

    @Resource
    HttpSessionUtils httpSessionUtils;

    @Resource
    InitBean initBean;


    /**
     * 验证权限
     * @param
     */
    public BaseResult oauth(HttpServletRequest request,InputEntity inputEntity){
        long beginTime = System.currentTimeMillis();

        BaseResult baseResult = validateSys();

        if(inputEntity.getEnableOnlyKeySecurity()){//如果采用密钥登录则说明采用第三方调用方式
            return validateKeySecurity(request);
        }

        if(StringUtil.isEmpty(inputEntity.getToken())){
            return new BaseResult("未能获取到客户端Token",false);
        }

        logTime(beginTime,inputEntity.getUrl());

        if(!baseResult.getSuccess()){
            return baseResult;
        }
        ///////////////////拦截IP黑户开始（优先级最高）///////////////////////
//        if(!validateIP(request)) {
//            if(!bDownLoad(request)){
//                return outAudStr(false,  StatusConstant.BDOWNFLAG_TEXT);
//            }
//            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_001,null,false);
//        }
        ///////////////////拦截IP黑户结束///////////////////////
        String requestUrl = inputEntity.getUrl();
        if(requestUrl.equals(PathConstant.REQUEST_ERROR)){
            return new BaseResult("Request exception",false);
        }

        //不需要登陆验证的URL
        //需要登录验证的URL（目前不使用该注解 若authUneedLogin不需要登录不满足 则其下所有方法必须默认为需登录条件）
//		AuthNeedLogin authNeedLogin=methodHandler.getMethodAnnotation(AuthNeedLogin.class);
        //如果获取到方法是无需登录则放开 让其走（优先级第二）
        if(!StringUtil.isEmpty(inputEntity.getAuthUneedLogin())){
            return new BaseResult("AuthUneedLogin---Success",true);
        }

        BaseHttpSessionEntity baseHttpSessionEntity = baseUtils.getBaseHttpSessionEntity();

        //过滤druid
        if(((requestUrl.indexOf(("druid"))> 0 ) && null == baseHttpSessionEntity)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"druid被访问时，session不存在",false);
        }

        //需要登录但无需拦截验证URL
        if(!StringUtil.isEmpty(inputEntity.getNeedLoginUnAuth())){
            //如果注解为需要用户登录 则判断该用户是否登录 如果登录了 则放开其操作该方法的权限 否则不通过
            if(null == baseHttpSessionEntity){
                logTime(beginTime,inputEntity.getUrl());
                return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"session不存在",false);
            }else{
                OauthAccountEntity oauthAccountEntity = baseUtils.getXtU();
                //更新Token失效时间
                updateExpire(oauthUtil.getTokenByAccountId(oauthAccountEntity.getId()),oauthAccountEntity.getId(),oauthUtil.getTokenInfo(request));//更新Token有效期（如果一直活跃则更新有效期，否则到期直接失效）
                logTime(beginTime,inputEntity.getUrl());
                return new BaseResult("NeedLoginUnAuth---Success",true);
            }
        }
        //验证当前用户是否登录（优先级第三）
        if(null == baseHttpSessionEntity){
            //未登陆Token不存在
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"登陆会话失效",false);
        }

        //对功能进行拦截开始
        OauthAccountEntity oauthAccountEntity = baseUtils.getXtU();
        //更新Token失效时间
        updateExpire(oauthUtil.getTokenByAccountId(oauthAccountEntity.getId()),oauthAccountEntity.getId(),oauthUtil.getTokenInfo(request));//更新Token有效期（如果一直活跃则更新有效期，否则到期直接失效）

        //如果超级管理员则放过所有功能
        if(isAdmin(baseHttpSessionEntity)){
            logTime(beginTime,inputEntity.getUrl());
            return new BaseResult("Admin---Success",true);
        }
        //非超级管理员则进行功能权限验证
        Map<String,String> oauthFunctionInfoUrlMap = baseHttpSessionEntity.getOauthFunctionInfoUrlMap();
        if(null == oauthFunctionInfoUrlMap.get(requestUrl)){
            logTime(beginTime,inputEntity.getUrl());
            //如果非附件操作权限
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_777,"无权限",false);
        }else{
            baseResult = dataAuth(request, requestUrl,baseHttpSessionEntity);
            logTime(beginTime,inputEntity.getUrl());
            return baseResult;
        }
        //////////////////对功能进行拦截结束///////////////////
    }

    /**
     * 处理数据权限
     * @param request
     * @param requestUrl
     * @return
     * @throws
     */
    public BaseResult dataAuth(HttpServletRequest request,String requestUrl, BaseHttpSessionEntity baseHttpSessionEntity){
        String[] paramNames = (String[])request.getParameterValues("systemUID");//唯一标志systemUID
        List<String> systemUandM = baseHttpSessionEntity.getSystemAM();
        List<String> sysUID = new ArrayList<String>();
        //如果系统唯一标志不为空 说明系统采用了数据权限
        if(null != paramNames){
            //参数组成的数组
            String systemUID = paramNames[0];
            String[] systemUIDarray = new String[]{};
            if(null != systemUID && !"".equals(systemUID)){
                systemUIDarray = systemUID.split(",");
            }
            if(null != systemUandM){
                int result = 0;
                for(String str:systemUandM){
                    String[] sysUandMarray = new String[]{};
                    if(!StringUtil.isEmpty(str)){
                        sysUandMarray = str.split("#");
                        if(null != sysUandMarray){
                            //判断方法和参数都匹配
                            if(("@"+sysUandMarray[1]+"@").indexOf("@"+requestUrl+"@") >= 0){
                                for(int j = 0; j<systemUIDarray.length;j++){
                                    if(sysUandMarray[0].equals(systemUIDarray[j])){
                                        //如果相等
                                        result = result+1;
                                    }
                                }
                            }
                        }
                    }
                }
                //如果参数全部符合则进入方法
                if(result != systemUIDarray.length){
                    //没有权限操作
                    return new BaseResult("您没有该操作权限,请与管理员联系!",false);
                }
            }
        }else{
            //否则过滤当前操作是否数据权限查询拦截
            //说明可能是第一次初始化读取数据
            if(null != systemUandM){
                for(String str: systemUandM){
                    String[] sysUandMarray = new String[]{};
                    if(!StringUtil.isEmpty(str)){
                        sysUandMarray = str.split("#");
                        if(("@"+sysUandMarray[1]+"@").indexOf("@"+requestUrl+"@") >= 0){
                            sysUID.add(sysUandMarray[0]);
                        }
                    }
                }
                request.setAttribute("sysUID", sysUID);//用户ID
            }
        }
        return new BaseResult("dataAuth----success!",true);
    }

    /**
     * 判断是否管理员
     * @param baseHttpSessionEntity
     * @return
     */
    public boolean isAdmin(BaseHttpSessionEntity baseHttpSessionEntity) {
        if(null != baseHttpSessionEntity){
            OauthAccountEntity oauthAccountEntity = baseHttpSessionEntity.getOauthAccountEntity();
            List<OauthAdminSysEntity> oauthAdminSysEntities = JsonUtil.toFList(baseHttpSessionEntity.getOauthAdminSysEntities(), OauthAdminSysEntity.class);
            if (null != oauthAccountEntity && null != oauthAdminSysEntities && !oauthAdminSysEntities.isEmpty()) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    /**
     * 验证第三方密钥（即平台分发的密钥）
     * @param request
     * @return
     */
    private BaseResult validateKeySecurity(HttpServletRequest request){
        String key = null;
        String security = null;
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String k = (String) headerNames.nextElement();
            if(k.toLowerCase().equals(CacheConstant.APP_KEY.toLowerCase())){
                key = request.getHeader(k);
            }
            if(k.toLowerCase().equals(CacheConstant.APP_SECURITY.toLowerCase())){
                security = request.getHeader(k);
            }
        }

        if(StringUtil.isEmpty(key)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"未能获取到平台密钥Key",false);
        }

        if(StringUtil.isEmpty(security)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"未能获取到平台秘钥Security",false);
        }
        String oauthKeyInfoJson = httpSessionUtils.getHashAttribute(CacheConstant.OAUTH_KEY,key);
        OauthKeyInfo oauthKeyInfo = JsonUtil.fromFJson(oauthKeyInfoJson,OauthKeyInfo.class);
        if(null == oauthKeyInfo || StringUtil.isEmpty(oauthKeyInfo.getAppSecret())){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"平台秘钥Key不存在",false);
        }
        String appSecret = oauthKeyInfo.getAppSecret();
        if(!security.equals(appSecret)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"平台秘钥Security不正确",false);
        }
        return BaseResult.success("平台密钥合法");
    }

    /**
     * 验证本平台给的密钥
     * @param
     * @return
     */
    private BaseResult validateSys(){
        String key = initBean.getJehcCloudKey();
        String pass = initBean.getJehcCloudSecurity();
        if(StringUtil.isEmpty(key)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"未能获取到平台Key",false);
        }
        if(StringUtil.isEmpty(pass)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"未能获取到平台秘钥",false);
        }
        String oauthKeyInfoJson = httpSessionUtils.getHashAttribute(CacheConstant.OAUTH_KEY,key);
        OauthKeyInfo oauthKeyInfo = JsonUtil.fromFJson(oauthKeyInfoJson,OauthKeyInfo.class);
        if(null == oauthKeyInfo || StringUtil.isEmpty(oauthKeyInfo.getAppSecret())){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"平台秘钥不存在",false);
        }
        String appSecret = oauthKeyInfo.getAppSecret();
        if(!pass.equals(appSecret)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"平台秘钥不正确",false);
        }
        return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_200,"平台秘钥合法",true,key);
    }

    /**
     *
     * @param beginTime
     * @param url
     */
    void logTime(Long beginTime,String url){
        log.info(url+"||{}||{}",beginTime,System.currentTimeMillis());
    }

    /**
     *  如果一直活跃更新Token失效时间
     * @param token
     * @param tokenInfo
     */
    public void updateExpire(String token,String clientId,String tokenInfo){
        if(httpSessionUtils.setAttributeExpTime(SessionConstant.TOKEN_STORE_PATH+token, tokenInfo,12)){
            httpSessionUtils.setAttributeExpTime(SessionConstant.ACCOUNT_STORE_PATH+clientId, token,12);//单独存放Account编号维护Token
        }
    }
}
